import { AGConnectFunctionImpl } from './AGConnectFunctionImpl';
import { FunctionCallable, FunctionResult } from '../../../../types'
import { FunctionLocalRequest } from '../server/request/FunctionLocalRequest';
import { FunctionBackend } from "../server/FunctionBackend";
import { FunctionRequest } from "../server/request/FunctionRequest";
import { AGCError, AGCErrorCode } from "@hw-agconnect/core-ohos";
import agconnect from '@hw-agconnect/api-ohos';

export class FunctionCallableImpl implements FunctionCallable {
  private readonly httpTriggerURI: string;
  private readonly identifier: string;
  static TAG: string = 'FunctionCallableImpl';
  timeout: number;
  private functionBackend: FunctionBackend;

  constructor(identifier: string, httpTriggerURI: string) {
    this.identifier = identifier;
    this.httpTriggerURI = httpTriggerURI;
    this.timeout = 70000;
    this.functionBackend = new FunctionBackend(identifier);
  }

  async call(reqBody?: any): Promise<FunctionResult> {
    let url = (agconnect.function(this.identifier) as AGConnectFunctionImpl).getEmulatorUrl();
    if (url) {
      return this.callLocal(url, reqBody);
    } else {
      return this.callRemote(reqBody);
    }
  }

  async callRemote(reqBody?: any): Promise<FunctionResult> {
    let requestBody = (reqBody === undefined || reqBody === '') ? {} : reqBody;
    let functionRequest: FunctionRequest = new FunctionRequest(this.identifier, this.httpTriggerURI, requestBody);
    let res = await this.functionBackend.doRequest(functionRequest, this.timeout, true, true).catch(error => {
      if (error?.code == AGCErrorCode.AGC_HTTP_ERROR && error?.message) {
        return Promise.reject(new AGCError(AGCErrorCode.AGC_HTTP_ERROR, error.message));
      }
      return Promise.reject(error);
    });

    return Promise.resolve(res);
  }

  async callLocal(url: string, reqBody?: any): Promise<FunctionResult> {
    let requestBody = (reqBody === undefined || reqBody === '') ? {} : reqBody;
    let localRequest: FunctionLocalRequest = new FunctionLocalRequest(this.identifier, this.httpTriggerURI, requestBody, url);
    let res = await this.functionBackend.doLocalRequest(localRequest).catch(error => {
      return Promise.reject(error);
    });

    return Promise.resolve(res);
  }

  getTimeout(): number {
    return this.timeout;
  }

  setTimeout(timeout: number): void {
    this.timeout = timeout;
  }
}